package internal

import (
	"game-server/base"
	"game-server/conf"
	"game-server/log"
	"game-server/msg"
	"time"
	"fmt"
	"math/rand"
)

var msgHeart map[int32]string
var roomTime map[int32]int64

func init() {
	msgHeart = make(map[int32]string)
	roomTime = make(map[int32]int64)
	skeleton.AfterFunc(time.Second*time.Duration(conf.Server.HeartBeat), checkTime)
	skeleton.AfterFunc(time.Second*time.Duration(conf.Server.RoomCron), checkRoom)
	skeleton.AfterFunc(time.Second*time.Duration(conf.Server.UserTimeOut), handleHeartBeat)
}

func checkTime() {
	l := len(base.RoomList)
	ll := int(l / 100)
	log.Info("checkTime == ", ll, base.RoomList)
	for i := 0; i <= ll; i++ {
		start := i
		end := (i + 1) * 100
		if end > l {
			end = l
		}
		rList := append([]int32{}, base.RoomList[start:end]...)
		log.Info("rList == ", rList)
		go heartPong(rList)
	}
	skeleton.AfterFunc(time.Second*time.Duration(conf.Server.HeartBeat), checkTime)
}

// 心跳消息
func handleHeartBeat( /*args []interface{}*/) {
	PONG := &msg.PONG{
		TIME: time.Now().Unix(),
	}

	for _, user := range base.UserList {
		if nil != base.InitConn[user] {
			base.InitConn[user].WriteMsg(PONG)
		}
	}
	skeleton.AfterFunc(time.Second*time.Duration(conf.Server.UserTimeOut), handleHeartBeat)
}

func heartPong(listHeart []int32) {
	t := time.Now().Unix()
	for _, v := range listHeart {
		log.Debug("heartPong v is ,,,,,,,,,,,,,,,,,,,,,,,,,", v)
		if base.IsExist("room", v) {
			roomInfoInter := base.Get("room", v)
			if roomInfoInter == nil{
				return
			}
			roomInfo := roomInfoInter.(base.Pk)
			for key, val := range roomInfo.Players {
				if nil == val {
					continue
				}
				if val.PlayerId <= 0 {
					continue
				}
				userInfo := base.Get("user", val.PlayerId).(base.PlayerInfo)
				if userInfo.RoomNo != roomInfo.RoomNo {
					log.Debug(" 干掉一个玩家 heat", val.PlayerId, userInfo.RoomNo, roomInfo.RoomNo)
					// todo 干掉一个玩家
					if roomInfo.Status == int32(msg.RoomState_IDLE){
						roomInfo.Players = append(roomInfo.Players[:key], roomInfo.Players[key+1:]...)
					}else {
						roomInfo.Players[key].PlayerId =  -1
					}
					base.Put("room",roomInfo.RoomNo,roomInfo)
					continue
				}
			}


			if roomInfo.Status == int32(msg.RoomState_START) {
				var players []int32
				ifChange := false
				for _, val := range roomInfo.Players {
					if nil == val {
						continue
					}

					if val.PlayerId <= 0 {
						continue
					}

					userInfo := base.Get("user", val.PlayerId).(base.PlayerInfo)
					if roomInfo.EggOwnerId != userInfo.PlayerId {
						players = append(players, val.PlayerId)
						continue
					}
					if userInfo.Online == false {
						// 托管状态
						nowTime := time.Now()
						getEggTime := time.Unix(roomInfo.GetEggTime, 0)
						log.Debug(" 托管", val.PlayerId, userInfo.RoomNo, roomInfo.RoomNo)
						endTime2 := getEggTime.Add(time.Duration(3) * time.Second)
						log.Debug("endTime2============", endTime2)
						log.Debug("nowTime============", nowTime)

						if nowTime.After(endTime2) {
							roomInfo.OpTime = t
							ifChange = true
						}
					}
				}
				if ifChange {

					if len(players) <= 0 {
						return
					}
					// todo 开始传递蛋
					log.Debug("托管传蛋")
					ChangeEggOwner(players, &roomInfo, roomInfo.EggOwnerId, true)
					//
					//length := len(players)
					//targerId := players[rand.Intn(length)]
					//roomInfo.GetEggTime = time.Now().Unix()
					//base.Put("room",roomInfo.RoomNo,roomInfo)
					//MsgChangeEggS2C := &msg.MsgChangeEggS2C{
					//	RoomId:   roomInfo.RoomNo,
					//	PlayerId: roomInfo.EggOwnerId,
					//	TargerId: targerId,
					//}
					//roomInfo.EggOwnerId = targerId
					//base.Put("room", roomInfo.RoomNo,roomInfo)
					//for _, v := range roomInfo.Players {
					//	if nil == v{
					//		continue
					//	}
					//
					//	if v.PlayerId <= 0 {
					//		continue
					//	}
					//
					//	if nil != base.InitConn[v.PlayerId] {
					//		base.InitConn[v.PlayerId].WriteMsg(MsgChangeEggS2C)
					//	}
					//}
				}
			}

		} else {
			log.Info("AutoRoom: room no exist !")
		}
	}
}

func checkRoom() {
	var roomList []int32
	roomList = append(roomList, base.RoomList...)
	roomList = append(roomList, base.RoomOver...)
	l := len(roomList)
	ll := int(l / 100)
	for i := 0; i <= ll; i++ {
		start := i
		end := (i + 1) * 100
		if end > l {
			end = l
		}
		rList := append([]int32{}, roomList[start:end]...)
		go cronRoom(rList)
	}
	skeleton.AfterFunc(time.Second*time.Duration(conf.Server.RoomCron), checkRoom)
}

func getRandom(roomInfo base.Pk) (random int) {
	var randoms [] int
	for key, v := range roomInfo.Players {
		if nil == v {
			continue
		}
		if v.PlayerId <= 0 {
			continue
		}
		randoms = append(randoms, key)
	}
	random = randoms[rand.Intn(int(len(randoms)))]
	return
}

func cronRoom(listRoom []int32) {
	t := time.Now().Unix()
	nowTime := time.Now()
	for _, v := range listRoom {
		log.Debug("==========================v is:", v)
		log.Debug("==========================v is:", base.IsExist("room", v))
		if base.IsExist("room", v) {
			roomInfo := base.Get("room", v).(base.Pk)
			ourRoom := 0
			for _, play := range roomInfo.Players {
				if nil == play {
					ourRoom += 1
				} else if play.PlayerId <= 0 {
					ourRoom += 1
				}
			}
			log.Debug("ourRoom is:",ourRoom)
			log.Debug("len(roomInfo.Players) is:",len(roomInfo.Players))

			if len(roomInfo.Players) == 0 || len(roomInfo.Players) == ourRoom {
				// 房间没人，删除房间
				log.Debug("房间没人，删除房间", roomInfo.RoomNo)
				roomInfo.Destroy = true
				base.Put("room", roomInfo.RoomNo, roomInfo)
				continue
			}

			log.Debug("==========================roomInfo.Status is:", roomInfo.Status)
			if roomInfo.Status == int32(msg.RoomState_Answer) {
				startIimeAns := time.Unix(roomInfo.AnswerTime, 0)
				endTimeAns := startIimeAns.Add(time.Duration(conf.Server.AnswerTimeOut) * time.Second)

				if endTimeAns.After(startIimeAns){
					//todo 超出答题实践算失败蛋爆炸

					MsgUseItemResult := msg.MsgUseItemResultS2C{
						RoomId:roomInfo.RoomNo,
						PlayerId:roomInfo.EggOwnerId,
						Result:0,
						Value1:1,
						Value2:0,
					}
					userItemAction(&roomInfo,MsgUseItemResult)
				}
				continue
			}

			if roomInfo.Status == int32(msg.RoomState_IDLE) {
				continue
			}
			fmt.Println("msg.RoomState(roomInfo.Status)", msg.RoomState(roomInfo.Status))
			switch msg.RoomState(roomInfo.Status) {
			case msg.RoomState_START:
				//todo 开始状态
				log.Debug("roomInfo.EggOwnerId ", roomInfo.EggOwnerId)
				if roomInfo.EggOwnerId == 0 {
					continue
				}
				startIime := time.Unix(roomInfo.StartGameTime, 0)
				endTime := startIime.Add(time.Duration(roomInfo.BoomTime) * time.Second)
				getEggTime := time.Unix(roomInfo.GetEggTime, 0)
				endTime2 := getEggTime.Add(time.Duration(30) * time.Second)

				log.Debug("startIime", startIime)
				log.Debug("endTime ", endTime)
				log.Debug("endTime2 ", endTime2)
				log.Debug("startIime.After(endTime)", startIime.After(endTime))
				log.Debug("startIime.After(endTime2)", startIime.After(endTime2))

				/// 开始时间 BoomTime 后爆炸
				if nowTime.After(endTime) {
					// todo 蛋爆炸
					log.Debug("蛋爆炸", t)
					BoomAction(&roomInfo, t)

				} else if nowTime.After(endTime2) {
					// todo 托管
					log.Debug(" 托管xxxx", roomInfo.RoomNo, roomInfo.Players)
					userInfo := base.Get("user", roomInfo.EggOwnerId).(base.PlayerInfo)
					userInfo.Online = false
					base.Put("user", userInfo.PlayerId, userInfo)

					MsgRobotS2C := &msg.MsgRobotS2C{
						PlayerId: roomInfo.EggOwnerId,
						IsRobot:  1,
					}

					for _, v := range roomInfo.Players {
						if v == nil {
							continue
						}

						if v.PlayerId <= 0 {
							continue
						}
						if nil != base.InitConn[v.PlayerId] {
							base.InitConn[v.PlayerId].WriteMsg(MsgRobotS2C)
						}
					}

				}
			case msg.RoomState_END:

				startIime_end := time.Unix(roomInfo.StartGameTime, 0)
				endTime_2 := startIime_end.Add(time.Duration(15) * time.Second)
				nowTime_2 := time.Now()
				log.Debug("startIime_end:==========", startIime_end)
				log.Debug("nowTime_2:==========", nowTime_2)
				log.Debug("endTime_2:==========", endTime_2)
				log.Debug("nowTime.After(endTime_2):==========", nowTime_2.After(endTime_2))

				if nowTime_2.After(endTime_2) {
					// todo 通知开始
					var players []*msg.PlayerInfo
					random := getRandom(roomInfo)

					log.Debug(" 修改时间--end", time.Unix(t, 0))
					roomInfo.OpenTime = t
					for _, v := range roomInfo.Players {
						if nil == v {
							continue
						}
						if v.PlayerId <= 0 {
							continue
						}
						//todo 通知房间信息变化
						MsgRoomStateS2C := &msg.MsgRoomStateS2C{
							RoomState: int32(msg.RoomState_START),
							Time:      3,
							EggOwner:  roomInfo.Players[random].PlayerId,
						}
						if base.InitConn[v.PlayerId] != nil {
							base.InitConn[v.PlayerId].WriteMsg(MsgRoomStateS2C)
						}

						playerInfoBase := base.Get("user",v.PlayerId).(base.PlayerInfo)
						tempPlay := newPlayerInfoMsg(&playerInfoBase)
						//msg.PlayerInfo{
						//	PlayerId: v.PlayerId,
						//	NickName: v.NickName,
						//	Gold:     v.Gold,
						//	Score:    v.Score,
						//	ItemId:   v.ItemId,
						//}
						players = append(players, &tempPlay)
					}
					BoomTime := int64(rand.Float64()*float64(conf.Server.MinBoomTime) + float64(conf.Server.MaxBoomTime-conf.Server.MinBoomTime))
					//todo 房间状态转换为开始状态
					RewardType := 1
					randomNum := int32(rand.Intn(100))
					if randomNum < 80 {
						RewardType = 2
					}

					roomInfo.Status = int32(msg.RoomState_START)
					roomInfo.EggOwnerId = roomInfo.Players[random].PlayerId //随机给一个人
					roomInfo.StartGameTime = time.Now().Unix()              // 游戏开始时间
					roomInfo.GetEggTime = time.Now().Unix()                 // 得到蛋的时间
					roomInfo.OpTime = time.Now().Unix()
					roomInfo.RewardType = int32(RewardType) //int32(rand.Intn(100)) % 2   //奖励类型
					roomInfo.BoomTime = BoomTime
					randValue := 100
					if roomInfo.RewardType == Reward_addItem {
						randValue = 2
					}
					roomInfo.Value = int32(rand.Intn(randValue)) //奖励value

					base.Put("room", roomInfo.RoomNo, roomInfo)

					//todo 通知玩家信息
					MsgEnterRoomS2C := &msg.MsgEnterRoomS2C{
						RoomId:    roomInfo.RoomNo,
						RoomRound: roomInfo.RoundId,
						WaitTime:  3,
						Players:   players,
					}
					for _, v := range roomInfo.Players {
						if v == nil {
							continue
						}

						if v.PlayerId <= 0 {
							continue
						}
						if base.InitConn[v.PlayerId] != nil {
							base.InitConn[v.PlayerId].WriteMsg(MsgEnterRoomS2C)
						}
					}

				}
			default:
				roomInfo.Status = int32(msg.RoomState_IDLE)
				base.Put("room", roomInfo.RoomNo, roomInfo)
			}
		} else {
			log.Info("CheckRoom: room no exist !")
		}
	}
}
